package com.msb.mall.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;

import com.msb.common.constant.ProductConstant;
import com.msb.mall.product.dao.AttrAttrgroupRelationDao;
import com.msb.mall.product.dao.AttrGroupDao;
import com.msb.mall.product.entity.AttrAttrgroupRelationEntity;
import com.msb.mall.product.entity.AttrGroupEntity;
import com.msb.mall.product.entity.CategoryEntity;
import com.msb.mall.product.service.AttrAttrgroupRelationService;
import com.msb.mall.product.service.AttrGroupService;
import com.msb.mall.product.service.CategoryService;
import com.msb.mall.product.vo.AttrGroupRelationVO;
import com.msb.mall.product.vo.AttrResponseVo;
import com.msb.mall.product.vo.AttrVO;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.msb.common.utils.PageUtils;
import com.msb.common.utils.Query;

import com.msb.mall.product.dao.AttrDao;
import com.msb.mall.product.entity.AttrEntity;
import com.msb.mall.product.service.AttrService;
import org.springframework.transaction.annotation.Transactional;


@Service("attrService")
public class AttrServiceImpl extends ServiceImpl<AttrDao, AttrEntity> implements AttrService {


    @Autowired
    AttrAttrgroupRelationService attrAttrgroupRelationService;

    @Autowired
    AttrGroupService attrGroupService;

    @Autowired
    CategoryService categoryService;

    @Autowired
    AttrService attrService;

    @Autowired
    AttrAttrgroupRelationDao attrAttrgroupRelationDao;

    @Autowired
    AttrGroupDao attrGroupDao;

    @Autowired
    AttrDao attrDao;



    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<AttrEntity> page = this.page(
                new Query<AttrEntity>().getPage(params),
                new QueryWrapper<AttrEntity>()
        );

        return new PageUtils(page);
    }


    /**
     * 属性新增
     *
     * @param attrVO
     */
    @Transactional
    @Override
    public void saveAttr(AttrVO attrVO) {
        //保存规格参数的正常信息
        AttrEntity attrEntity = new AttrEntity();
        BeanUtils.copyProperties(attrVO, attrEntity);
        this.save(attrEntity);

        //保存规格参数对应的属性组信息
        if (attrVO.getAttrGroupId() != null && attrVO.getAttrType()== ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()) {

            AttrAttrgroupRelationEntity attrAttrgroupRelationEntity = new AttrAttrgroupRelationEntity();

            //设置相关的属性
            attrAttrgroupRelationEntity.setAttrGroupId(attrVO.getAttrGroupId());
            //todo 因为AttrVO中的AttrId在上面复制用掉了，所有不能用attrVO.getAttrId()，应该用attrEntity.getAttrId()，否则会报错
            attrAttrgroupRelationEntity.setAttrId(attrEntity.getAttrId());

            //将关联的参数添加到对应关联表中
            attrAttrgroupRelationService.save(attrAttrgroupRelationEntity);


        }


    }


    /**
     * 分页查询,下面也是一种写法，品牌，属性组跟下面这个写法一样
     *
     * @param params
     * @param catelogId
     * @param attrtype
     * @return
     */
    @Override
    public PageUtils queryBasePage(Map<String, Object> params, Long catelogId, String attrtype) {


        QueryWrapper<AttrEntity> wrapper = new QueryWrapper<>();

        wrapper.eq("attr_type","base".equalsIgnoreCase(attrtype)?1:0);
        // 1.根据类别编号查询
        if(catelogId != 0 ){
            wrapper.eq("catelog_id",catelogId);
        }
        // 2.根据key 模糊查询
        String key = (String) params.get("key");
        if(!StringUtils.isEmpty(key)){
            wrapper.and((w)->{
                w.eq("attr_id",key).or().like("attr_name",key);
            });
        }
        // 3.分页查询
        IPage<AttrEntity> page = this.page(
                new Query<AttrEntity>().getPage(params),
                wrapper
        );
        PageUtils pageUtils = new PageUtils(page);
        // 4. 关联的我们需要查询出类别名称和属性组的名称
        //获取总记录数
        List<AttrEntity> records = page.getRecords();
        List<AttrResponseVo> list = records.stream().map((attrEntity) -> {
            AttrResponseVo responseVo = new AttrResponseVo();
            BeanUtils.copyProperties(attrEntity, responseVo);
            // 查询每一条结果对应的 类别名称
            CategoryEntity categoryEntity = categoryService.getById(attrEntity.getCatelogId());
            if (categoryEntity != null) {
                responseVo.setCatelogName(categoryEntity.getName());
            }
            // 设置属性组的名称
           /*  todo 老师这里写了这个，我也看不到懂它在这里作用，但是我注释掉之后发现对功能没有影响，所以就看看后面对项目有没有影响
           AttrAttrgroupRelationEntity entity = new AttrAttrgroupRelationEntity();
            entity.setAttrId(attrEntity.getAttrId());*/
            // 去关联表中找到对应的属性组ID,并判断下面是否是基本属性，是就放行
            if ("base".equalsIgnoreCase(attrtype)){

                AttrAttrgroupRelationEntity attrAttrgroupRelationEntity = attrAttrgroupRelationDao
                        .selectOne(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrEntity.getAttrId()));
                if (attrAttrgroupRelationEntity != null && attrAttrgroupRelationEntity.getAttrGroupId() != null) {
                    // 获取到属性组的ID，然后根据属性组的ID我们来查询属性组的名称
                    AttrGroupEntity attrGroupEntity = attrGroupService.getById(attrAttrgroupRelationEntity.getAttrGroupId());
                    responseVo.setAttrgroupName(attrGroupEntity.getAttrGroupName());
                }
            }

            return responseVo;
            //把数据整理成list集合
        }).collect(Collectors.toList());
        pageUtils.setList(list);
        return pageUtils;




    }

    /**
     * 查询并设置相关的关联信息响应到前端
     * @param attrId
     * @return
     */
    @Override
    public AttrResponseVo getAttrInfo(Long attrId) {
            // 声明返回的对象
         AttrResponseVo attrResponseVo = new AttrResponseVo();

        // 1.根据ID查询规格参数的基本信息
         AttrEntity attrEntity = this.getById(attrId);
        BeanUtils.copyProperties(attrEntity,attrResponseVo);

        // 2.查询关联的属性组信息 中间表
        if(attrEntity.getAttrType()==ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()){
            AttrAttrgroupRelationEntity attrAttrgroupRelationEntity =
                    attrAttrgroupRelationService.getOne(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrId));
            if (attrAttrgroupRelationEntity!=null){
                AttrGroupEntity attrgroupentity =
                        attrGroupService.getOne(new QueryWrapper<AttrGroupEntity>().eq("attr_group_id", attrAttrgroupRelationEntity.getAttrGroupId()));
                attrResponseVo.setAttrGroupId(attrgroupentity.getAttrGroupId());
                if(attrgroupentity!=null){
                    //设置属性组名称
                    attrResponseVo.setAttrgroupName(attrgroupentity.getAttrGroupName());
                }
            }
        }

        // 3.查询关联的类别信息
         Long catelogId = attrEntity.getCatelogId();
       Long[] path = categoryService.findCatelogPath(catelogId);
       attrResponseVo.setCatelogPath(path);

       CategoryEntity categoryEntity = categoryService.getById(catelogId);
       if (categoryEntity!=null){
            //设置类别名称
           attrResponseVo.setCatelogName(categoryEntity.getName());
       }


        return attrResponseVo;
    }

    /**
     * 更新数据
     * @param attr
     */
    @Transactional
    @Override
    public void updateBaseAttr(AttrResponseVo attr) {

        AttrEntity entity = new AttrEntity();
        BeanUtils.copyProperties(attr, entity);
        // 1.更新基本数据
        this.updateById(entity);
        // 2.修改分组关联的关系
        if (attr.getAttrType()==ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()){AttrAttrgroupRelationEntity relationEntity = new AttrAttrgroupRelationEntity();
            relationEntity.setAttrId(entity.getAttrId());
            relationEntity.setAttrGroupId(attr.getAttrGroupId());
            // 判断关联表是否存在对应的数据
            Integer count = attrAttrgroupRelationDao.selectCount(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attr.getAttrId()));
            if (count > 0) {
                // 说明有记录，直接更新
                attrAttrgroupRelationDao.update(relationEntity, new UpdateWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attr.getAttrId()));
            } else {
                // 说明没有记录，直接插入
                attrAttrgroupRelationDao.insert(relationEntity);

            }}

    }



    /**
     * 根据attrIds删除基本属性表，属性关联表
     * 或者删除销售属性表，但是没有关联表
     * @param attrIds
     */
    @Override
    public void removeByIdsDetails(Long[] attrIds) {

        //删除基本属性表和销售属性表
        attrService.removeByIds(Arrays.asList(attrIds));
        //删除基本属性表关联表
      for (Long attrid: attrIds){
          AttrEntity byId = this.getById(attrid);
          if (byId!=null && byId.getAttrType().equals(ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode())){}

          attrAttrgroupRelationDao.delete(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrid));
      }
    }


    /**
     * 根据属性组编号查询对应的基本信息
     * @param attrgroupid
     * @return
     */
    @Override
    public List<AttrEntity> getRelationAttr(Long attrgroupid) {

         List<AttrAttrgroupRelationEntity> list = attrAttrgroupRelationDao.selectList(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_group_id", attrgroupid));
         List<AttrEntity> attrentitys= list.stream().map((obj) -> {
            AttrEntity attrEntity = this.getById(obj.getAttrId());
            return attrEntity;
        }).filter(attrEntity -> attrEntity != null).collect(Collectors.toList());

        return attrentitys;
    }



    /**
     * 解除属性组和基本属性的关联关系
     *    也就是删除 属性组和属性关联表中的记录
     * @param vos
     */
    @Override
    public void deleteRelation(AttrGroupRelationVO[] vos) {
        // 将我们接收数据的对象转为了一个 entity 实体对象
        List<AttrAttrgroupRelationEntity> list = Arrays.asList(vos).stream().map((item) -> {
            AttrAttrgroupRelationEntity entity = new AttrAttrgroupRelationEntity();
            BeanUtils.copyProperties(item, entity);
            return entity;
        }).collect(Collectors.toList());
        // 批量的删除关联表中的数据
        attrAttrgroupRelationDao.removeBatchRelation(list);
    }


    /**
     * 根据属性组的ID查询出未被关联的属性信息
     * 1.查询出所有的属性信息
     *   我们找到的属性信息必须是和属性组的类别相同的属性
     * 2.查询出当前属性组关联的属性信息
     * 3.1中排除掉2中的属性，剩下的就是我们要查找的属性信息
     * @param param
     * @param attrgroupid
     * @return
     */
    @Override
    public PageUtils getNoAttrRelation(Long attrgroupid, Map<String, Object> param) {

        // 1.查询当前属性组所在的类别编号
        AttrGroupEntity attrGroupEntity = attrGroupService.getById(attrgroupid);
        // 获取到对应的分类id
        Long catelogId = attrGroupEntity.getCatelogId();
        // 2.当前分组只能关联自己所属的类别下其他的分组没有关联的属性信息。
        // 先找到这个类别下的所有的分组信息
        List<AttrGroupEntity> group = attrGroupDao.selectList(new QueryWrapper<AttrGroupEntity>().eq("catelog_id", catelogId));
        // 获取属性组的编号集合
        List<Long> groupIds = group.stream().map((g) -> g.getAttrGroupId()).collect(Collectors.toList());
        // 然后查询出类别信息下所有的属性组已经分配的属性信息
        List<AttrAttrgroupRelationEntity> relationEntities = attrAttrgroupRelationDao.selectList(new QueryWrapper<AttrAttrgroupRelationEntity>().in("attr_group_id", groupIds));
        List<Long> attrIds = relationEntities.stream().map((m) -> m.getAttrId()).collect(Collectors.toList());
        // 根据类别编号查询所有的属性信息并排除掉上面的属性信息即可
        // 这其实就是需要查询出最终返回给调用者的信息了  分页  带条件查询
        QueryWrapper<AttrEntity> wrapper = new QueryWrapper<AttrEntity>()
                .eq("catelog_id",catelogId)
                // 查询的是基本属性信息，不需要查询销售属性信息
                .eq("attr_type",ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode());
        // 然后添加排除的条件
        if(attrIds != null && attrIds.size() > 0){
            wrapper.notIn("attr_id",attrIds);
        }
        // 还有根据key的查询操作
        String key = (String)param.get("key");
        if(!StringUtils.isEmpty(key)){
            wrapper.and((w)->{
                w.eq("attr_id",key).or().like("attr_name",key);
            });
        }
        // 查询对应的相关信息
        IPage<AttrEntity> page = this.page(
                new Query<AttrEntity>().getPage(param),
                wrapper
        );

        return new PageUtils(page);
    }

    /**
     * 查找出可以检索的规格参数（基本属性）
     * @param basearrtIds
     * @return
     */
    @Override
    public List<Long> selectSearchAttrIds(List<Long> basearrtIds) {
        //1.查找出可以检索的规格参数（基本属性）
        List<AttrEntity> list
                = this.list(new QueryWrapper<AttrEntity>().in("attr_id", basearrtIds).eq("search_type", 1));

        //2.获取所有可以检索的attrId
        List<Long> collect = list.stream().map((m -> {

            return m.getAttrId();
        })).collect(Collectors.toList());


        return collect;
    }
}
